/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package perplexity;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 *
 * @author Martin Haulrich
 */
public class PerplexityCalculator {

    final int N;

    final EstimatorPer est;

    public PerplexityCalculator(EstimatorPer est, int N) {
        this.est = est;
        this.N = N;
    }

    public double[] calculate(String filename) throws Exception {

        BufferedReader input = new BufferedReader(new FileReader(filename));
        String line;
        int wordsCount = 0;
        int allTokensCount = 0;
        double logPropAll = 0;
        int totUnk=0;
        int lc = 0;
        while ((line = input.readLine()) != null) {
        //    System.err.println("Line: " + (++lc));
            String[] tokensArr = line.split(" ");
            List<String> tokens = new ArrayList<String>(Arrays.asList(tokensArr));
            tokens.add(0, "<s>");
//            tokens.add(0, "<s>");
            //  for (int i = 0; i < N - 1; i++) {

            double logProbSentence = 0;
            tokens.add("</s>");
            int zeroProbsCount = 0;
            //   }
            //  System.err.println("N " + N + "   " +tokens);

//            for (int n = 1; n < N; n++) {
//                List<String> ngram = tokens.subList(0, n);
//                logPropProd = logPropProd + est.getEstimate(ngram);
//                System.err.println("uni: " + ngram + " " + est.getEstimate(ngram));
//                
//            }
            if (N > 2) {
                for (int i = 1; i < N - 1; i++) {
                    List<String> initialngram = tokens.subList(0, N - i);
                    System.err.println("ini " + initialngram);

                    double iniProb = est.getEstimate(initialngram);
                    if (Double.NEGATIVE_INFINITY != iniProb) {
                        logProbSentence = logProbSentence + iniProb;

                    } else {
                        zeroProbsCount++;
                    }
                    System.err.println("ini " + iniProb);
                }
            }

            for (int i = (N - 1); i < tokens.size(); i++) {
                List<String> ngram = tokens.subList(i - (N - 1), i + 1);
                double ngramEst = est.getEstimate(ngram);
                if (Double.NEGATIVE_INFINITY != ngramEst) {
                    logProbSentence = logProbSentence + ngramEst;
                } else {
                    zeroProbsCount++;

                }
                System.err.println(ngram + ";" + ngramEst);

            }
            logPropAll = logPropAll + logProbSentence;
            //       System.err.println("---- " + logProbSentence + " -------");
            wordsCount = wordsCount + tokensArr.length - zeroProbsCount;
            allTokensCount = allTokensCount + tokensArr.length + 1 - zeroProbsCount;
                totUnk+=zeroProbsCount;
        }

        System.err.println(logPropAll);
        double logPPL1 = logPropAll / ((double) -wordsCount);
        double logPPL = logPropAll / ((double) -allTokensCount);
        System.err.println("wc" + wordsCount);
        System.err.println("at" + allTokensCount);
        double ppl = Math.pow(10, logPPL);
        double ppl1 = Math.pow(10, logPPL1);
        System.err.println("ppl: " + logPPL + "   " + ppl);
        System.err.println("ppl1: " + logPPL1 + "   " + ppl1);


        double[] resA = new double[4];
        resA[0]=logPropAll;
        resA[1]=ppl;
        resA[2]=ppl1;
        resA[3]=(double) totUnk ;
        return resA;
    }
}
